package io.renren.modules.medical.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.exception.MedicalException;
import io.renren.common.result.ResultCodeEnum;
import io.renren.common.utils.*;
import io.renren.modules.medical.dao.VisitRecordDao;
import io.renren.modules.medical.entity.*;
import io.renren.modules.medical.service.*;
import io.renren.modules.medical.vo.medicalVo.VisitRecordListVo;
import io.renren.modules.medical.vo.medicalVo.VisitRecordSaveVo;
import io.renren.modules.medical.vo.weixinVo.ApiVisitRecordStepVo;
import io.renren.modules.sys.service.SysUserRoleService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Service("visitRecordService")
public class VisitRecordServiceImpl extends ServiceImpl<VisitRecordDao, VisitRecordEntity> implements VisitRecordService {

    private final PatientInfoService patientInfoService;

    private final IllSubService illSubService;

    private final DoctorInfoService doctorInfoService;

    private final VisitRecordStepService visitRecordStepService;

    private final SysUserRoleService sysUserRoleService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        LambdaQueryWrapper<VisitRecordEntity> queryWrapper = new LambdaQueryWrapper<VisitRecordEntity>();
        String key = (String)params.get("key");
        // 根据原有参数获取原有的HealthGuidanceEntity集合
        if (StringUtils.isNotEmpty(key) && StringUtils.isNumeric(key)){
            Long patientId = Long.valueOf(key);
            queryWrapper.eq(VisitRecordEntity::getPatientId, patientId);
        }else if (StringUtils.isNotEmpty(key)){
            List<Long> patientIds = patientInfoService.getIdsByName(key);
            queryWrapper.in(patientIds != null && patientIds.size() > 0,
                    VisitRecordEntity::getPatientId, patientIds);
        }

        // 判断当前用户是医生还是管理员或者审核
        List<Long> roles = DoctorInfoUtils.getRole(sysUserRoleService);
        if ( roles.contains(Constant.SysRole.ADMIN.getValue()) ){
            // 访问全部
        }else if( roles.contains(Constant.SysRole.DOCTOR.getValue()) ){
            // 医生就只访问当前医生创建的
            DoctorInfoEntity doctorInfo = DoctorInfoUtils.getDoctorInfo(doctorInfoService);
            queryWrapper.eq(QueryPageBaseEntity::getDoctorId, doctorInfo.getId());
        }else{
            throw new MedicalException(HttpStatus.SC_FORBIDDEN, "用户无权访问健康指导列表");
        }

        // 根据修改时间排序
        queryWrapper.orderByDesc(BaseEntity::getUpdateTime);
        IPage<VisitRecordEntity> page = this.page(
                new Query<VisitRecordEntity>().getPage(params),
                queryWrapper
        );
        // 封装集合作为页面返回值
        List<VisitRecordEntity> records = page.getRecords();
        List<VisitRecordListVo> visitRecordListVos = records.stream().map(
                // 调用方法将需要的属性封装进来
                item -> (VisitRecordListVo) QueryPageUtils.listToVos(new VisitRecordListVo(), item, patientInfoService, illSubService, doctorInfoService)
        ).collect(Collectors.toList());

        String visit = (String)params.get("visit");
        if (visit.equals("1")){
            visitRecordListVos = visitRecordListVos.stream().filter(item -> waitReply(item) && item.getVisitStatus() == Constant.VisitStatus.NVISITED.getValue()).collect(Collectors.toList());
        }

        Page<VisitRecordListVo> visitRecordVoPage = new Page<>();
        BeanUtils.copyProperties(page, visitRecordVoPage);
        visitRecordVoPage.setRecords(visitRecordListVos);
        return new PageUtils(visitRecordVoPage);
    }

    /**
     * 是否待回复
     * @return
     * @param filterItem
     */
    public boolean waitReply(VisitRecordListVo filterItem){
        Long id = filterItem.getId();
        // 通过Id找到所有的阶段数据
        List<VisitRecordStepEntity> stepList = visitRecordStepService.getStepList(id);
        if(stepList == null || stepList.size() <= 0){
            return false;
        }
        for (VisitRecordStepEntity stepEntity : stepList) {
            if (stepEntity.getStatus() == Constant.VisitStepStatus.WAIT_REPLY.getValue()){
                return false;
            }
        }
        return true;
    }

    @Transactional
    @Override
    public void saveVisitRecord(VisitRecordSaveVo visitRecord) {
        Long doctorId = DoctorInfoUtils.getDoctorInfo(doctorInfoService).getId();
        visitRecord.setDoctorId(doctorId);
        VisitRecordEntity visitRecordEntity = new VisitRecordEntity();
        BeanUtils.copyProperties(visitRecord, visitRecordEntity);
        // 先保存记录表
        this.save(visitRecordEntity);
        saveVisitStep(visitRecord, visitRecordEntity);
    }

    private void saveVisitStep(VisitRecordSaveVo visitRecord, VisitRecordEntity visitRecordEntity) {
        Long visitRecordId = visitRecordEntity.getId();
        String visitStep = visitRecord.getVisitStep();
        String[] visitStepStr = visitStep.split("/");

        // 保存步骤一
        VisitRecordStepEntity visitFirstRecordStepEntity = new VisitRecordStepEntity();
        if (visitStepStr[0].contains("、")){
            visitFirstRecordStepEntity.setVisitTitle(visitStepStr[0].substring(visitStepStr[0].indexOf("、") + 1));
        }else{
            visitFirstRecordStepEntity.setVisitTitle(visitStepStr[0]);
        }
        visitFirstRecordStepEntity.setVisitContent(visitRecord.getFirstVisitContent());
        visitFirstRecordStepEntity.setVisitRecordId(visitRecordId);
        visitFirstRecordStepEntity.setVisitStep(1);
        visitFirstRecordStepEntity.setStatus(Constant.VisitStepStatus.WAIT_REPLY.getValue());
        visitRecordStepService.save(visitFirstRecordStepEntity);

        // 遍历保存
        for (int i = 1; i < visitStepStr.length; i++){
            VisitRecordStepEntity visitRecordStepEntity = new VisitRecordStepEntity();
            if (visitStepStr[i].contains("、")){
                visitRecordStepEntity.setVisitTitle(visitStepStr[i].substring(visitStepStr[i].indexOf("、") + 1));
            }else{
                visitRecordStepEntity.setVisitTitle(visitStepStr[i]);
            }
            visitRecordStepEntity.setVisitRecordId(visitRecordId);
            visitRecordStepEntity.setVisitStep(i + 1);
            visitRecordStepService.save(visitRecordStepEntity);
        }
    }

    /**
     * 微信端获取到随访记录集合
     * @return
     */
    @Override
    public Map<String, List<VisitRecordEntity>> getRecord() {
        // 先获取到用户的id
        Long patientId = 1L;
        LambdaQueryWrapper<VisitRecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(QueryPageBaseEntity::getPatientId, patientId);
        queryWrapper.orderByDesc(VisitRecordEntity::getVisitCount);
        // 先获取到所有的随访
        List<VisitRecordEntity> visitRecordList = this.list(queryWrapper);

        // 过滤出未完成的
        List<VisitRecordEntity> noneFinishList = visitRecordList.stream()
                .filter(item -> item.getVisitStatus().equals(Constant.VisitStatus.NVISITED.getValue()))
                .map(item -> {
                    List<VisitRecordStepEntity> stepList = visitRecordStepService.getStepList(item.getId());
                    if (stepList == null || stepList.size() <= 0){
                        return null;
                    }
                    AtomicInteger active = new AtomicInteger(-1); // 步骤条参数
                    AtomicInteger waitReply = new AtomicInteger(); // 完善随访按钮是否显示
                    List<ApiVisitRecordStepVo> stepListVo = stepList.stream().map(stepItem -> {
                        ApiVisitRecordStepVo apiVisitRecordStepVo = new ApiVisitRecordStepVo();
                        apiVisitRecordStepVo.setId(stepItem.getId());
                        apiVisitRecordStepVo.setTitle(stepItem.getVisitTitle());
                        apiVisitRecordStepVo.setDesc(stepItem.getReplyTime() != null ? DateUtils.format(stepItem.getReplyTime()) : "");
                        if (stepItem.getStatus() == Constant.VisitStepStatus.FINISHED.getValue()){
                            active.addAndGet(1);
                        }
                        if (stepItem.getStatus() == Constant.VisitStepStatus.WAIT_REPLY.getValue()){
                            waitReply.set(1);
                        }
                        return apiVisitRecordStepVo;
                    }).collect(Collectors.toList());

                    Long doctorId = item.getDoctorId();
                    DoctorInfoEntity doctorInfo = doctorInfoService.getById(doctorId);
                    Long subId = item.getSubId();
                    IllSubEntity subEntity = illSubService.getById(subId);
                    item.getParam().put("active", active);
                    item.getParam().put("doctorName", doctorInfo.getName());
                    item.getParam().put("subTitle", subEntity.getTitle());
                    item.getParam().put("stepList", stepListVo);
                    item.getParam().put("waitReply", waitReply);
                    return item;
                }).filter(Objects::nonNull).collect(Collectors.toList());

        // 过滤出已完成
        List<VisitRecordEntity> finishList = visitRecordList.stream()
                .filter(item -> item.getVisitStatus().equals(Constant.VisitStatus.VISITED.getValue()))
                .map(item -> {
                    List<VisitRecordStepEntity> stepList = visitRecordStepService.getStepList(item.getId());
                    if (stepList == null || stepList.size() <= 0) {
                        return null;
                    }

                    AtomicInteger active = new AtomicInteger(-1);
                    AtomicInteger waitReply = new AtomicInteger(); // 完善随访按钮是否显示
                    List<ApiVisitRecordStepVo> stepListVo = stepList.stream().map(stepItem -> {
                        ApiVisitRecordStepVo apiVisitRecordStepVo = new ApiVisitRecordStepVo();
                        apiVisitRecordStepVo.setId(stepItem.getId());
                        apiVisitRecordStepVo.setTitle(stepItem.getVisitTitle());
                        apiVisitRecordStepVo.setDesc(stepItem.getReplyTime() != null ? DateUtils.format(stepItem.getReplyTime()) : "");
                        if (stepItem.getStatus() == Constant.VisitStepStatus.FINISHED.getValue()){
                            active.addAndGet(1);
                        }
                        if (stepItem.getStatus() == Constant.VisitStepStatus.WAIT_REPLY.getValue()){
                            waitReply.set(1);
                        }
                        return apiVisitRecordStepVo;
                    }).collect(Collectors.toList());

                    Long doctorId = item.getDoctorId();
                    DoctorInfoEntity doctorInfo = doctorInfoService.getById(doctorId);
                    Long subId = item.getSubId();
                    IllSubEntity subEntity = illSubService.getById(subId);
                    item.getParam().put("active", active);
                    item.getParam().put("doctorName", doctorInfo.getName());
                    item.getParam().put("subTitle", subEntity.getTitle());
                    item.getParam().put("stepList", stepListVo);
                    item.getParam().put("waitReply", waitReply);
                    return item;
                }).filter(Objects::nonNull).collect(Collectors.toList());

        HashMap<String, List<VisitRecordEntity>> resultMap = new HashMap<>();
        resultMap.put("noneFinishList", noneFinishList);
        resultMap.put("finishList", finishList);
        return resultMap;
    }

    /**
     * 微信端获取随访细节
     * @return
     * @param id
     */
    @Override
    public VisitRecordStepEntity getDetail(Long id) {
        VisitRecordEntity recordEntity = null;
        if (id != null){
            recordEntity = this.getById(id);
        }
        if (recordEntity == null){
            throw new MedicalException(ResultCodeEnum.NOT_FIND_ERROR.getCode(), "未找到对应的随访记录");
        }
        // 查询所有的对方阶段数据
        List<VisitRecordStepEntity> stepList = visitRecordStepService.getStepList(id);
        if (stepList == null || stepList.size() <= 0){
            throw new MedicalException(ResultCodeEnum.NOT_FIND_ERROR.getCode(), "空对象异常");
        }
        List<VisitRecordStepEntity> waitReplyList = stepList.stream().filter(item -> item.getStatus() == Constant.VisitStepStatus.WAIT_REPLY.getValue()).collect(Collectors.toList());
        if (waitReplyList.size() <= 0){
            throw new MedicalException(ResultCodeEnum.NOT_FIND_ERROR.getCode(), "空对象异常");
        }

         return waitReplyList.get(0);
    }

    /**
     * 提交表单
     * @param stepEntity
     */
    @Override
    public void confirm(VisitRecordStepEntity stepEntity) {
        Long visitRecordId = stepEntity.getVisitRecordId();
        VisitRecordStepEntity entity = visitRecordStepService.getById(stepEntity.getId());
        stepEntity.setStatus(Constant.VisitStepStatus.FINISHED.getValue());
        stepEntity.setReplyTime(new Date());
        visitRecordStepService.updateById(stepEntity);
        LambdaQueryWrapper<VisitRecordStepEntity> visitRecordStepWrapper = new LambdaQueryWrapper<>();
        visitRecordStepWrapper.eq(VisitRecordStepEntity::getVisitRecordId, visitRecordId);
        Integer stepCount = visitRecordStepService.count(visitRecordStepWrapper);

        if (stepCount.equals(entity.getVisitStep())){
            // 如果步骤和总数相同，说明已经到了最后一个，将visitRecord表更新为完成
            VisitRecordEntity visitRecordEntity = new VisitRecordEntity();
            visitRecordEntity.setVisitStatus(Constant.VisitStatus.VISITED.getValue());
            visitRecordEntity.setId(visitRecordId);
            this.updateById(visitRecordEntity);
        }
    }

    /**
     * 获取详情
     * @param id
     * @return
     */
    @Override
    public VisitRecordEntity getRecordDetail(Long id) {
        VisitRecordEntity visitRecord = this.getById(id);
        // 通过visitRecordId获取到步骤信息
        List<VisitRecordStepEntity> stepList = visitRecordStepService.getStepList(id);
        visitRecord.getParam().put("stepList", stepList);
        return visitRecord;
    }

    @Transactional
    @Override
    public void removeVisitRecord(List<Long> removeIds) {
        // 先找到对应的所有阶段表的id集合
        List<VisitRecordEntity> removeList = this.listByIds(removeIds);
        if (removeList == null || removeList.size() <= 0){
            throw new MedicalException(ResultCodeEnum.NOT_FIND_ERROR.getCode(), ResultCodeEnum.NOT_FIND_ERROR.getMessage());
        }
        LambdaQueryWrapper<VisitRecordStepEntity> visitRecordStepWrapper = new LambdaQueryWrapper<>();
        visitRecordStepWrapper.in(VisitRecordStepEntity::getVisitRecordId, removeIds);
        List<VisitRecordStepEntity> stepEntityList = visitRecordStepService.list(visitRecordStepWrapper);
        List<Long> removeStepIds = stepEntityList.stream().map(BaseEntity::getId).collect(Collectors.toList());
        visitRecordStepService.removeByIds(removeStepIds);
        this.removeByIds(removeIds);
    }

    /**
     * 新增阶段表数据
     * @param visitRecordStepEntity
     */
    @Transactional
    @Override
    public void saveStep(VisitRecordStepEntity visitRecordStepEntity) {
        LambdaQueryWrapper<VisitRecordStepEntity> visitRecordStepWrapper = new LambdaQueryWrapper<>();
        visitRecordStepWrapper.eq(VisitRecordStepEntity::getVisitRecordId, visitRecordStepEntity.getVisitRecordId());
        int count = visitRecordStepService.count(visitRecordStepWrapper);
        visitRecordStepEntity.setVisitStep(count + 1);
        visitRecordStepEntity.setStatus(Constant.VisitStepStatus.WAIT_SEND.getValue());
        visitRecordStepService.save(visitRecordStepEntity);
        VisitRecordEntity visitRecordEntity = new VisitRecordEntity();
        visitRecordEntity.setVisitStatus(0);
        visitRecordEntity.setId(visitRecordStepEntity.getVisitRecordId());
        this.updateById(visitRecordEntity);
    }

}